package com.haidechizi.i18n.common.execute.strategy;

import com.google.common.collect.Lists;
import com.haidechizi.i18n.common.annotation.I18nField;
import com.haidechizi.i18n.common.annotation.I18nModel;
import com.haidechizi.i18n.common.entity.I18nEntity;
import com.haidechizi.i18n.common.enums.annotation.I18nEnumField;
import com.haidechizi.i18n.common.enums.service.TranslateService;
import com.haidechizi.i18n.common.execute.AbstractTranslateExecute;
import com.haidechizi.i18n.common.support.I18nReflectUtils;
import com.haidechizi.i18n.common.translate.Translator;
import com.haidechizi.i18n.common.utils.GlobalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 将有层级的结构变成同级结构
 * 然后进行国际化
 */
@Slf4j
public class FlareOutTranslateExecute extends AbstractTranslateExecute {

    private static final String NAME = "flare_out";

    @Autowired(required = false)
    private TranslateService translateService;

    @Override
    public void processI18nFields(List<Object> models) {
        if (CollectionUtils.isEmpty(models)) {
            return;
        }

        // 进行递归，构建关系
        Map<String, I18nEntity> map = new HashMap<>();
        initModel(models, map);
        if (map.isEmpty()) {
            return;
        }
        processFields(map);

    }

    private void processSimpleField(I18nEntity i18nEntity) {
        String businessCode = i18nEntity.getBusinessCode();
        if (StringUtils.isEmpty(businessCode)) {
            return;
        }
        String languageName = GlobalUtils.getLanguage();
        Map<String, Map<String, String>> idFieldsMapModel = i18nInfoUtils.queryLocaleInfo(i18nEntity.getSystemCode(),
                businessCode, languageName, i18nEntity.getKeyList());
        if (idFieldsMapModel.isEmpty()) {
            log.info("国际化平台无相关国际化数据，跳过循环,系统Code：{}, 业务code：{}, 语言：{}, 业务主键:{},国际化结果：{}",
                    i18nEntity.getSystemCode(), businessCode, languageName, i18nEntity.getKeyList(), idFieldsMapModel);
            return;
        }
        for (Map.Entry<String, List<Object>> entry : i18nEntity.getObjectMap().entrySet()) {
            Map<String, String> fieldMap = idFieldsMapModel.get(entry.getKey());
            if (fieldMap == null || fieldMap.isEmpty()) {
                log.debug("国际化平台无相关国际化数据，跳过循环,系统Code：{}, 业务code：{}, 语言：{}, 业务主键:{},国际化结果：{}",
                        i18nEntity.getSystemCode(), businessCode, languageName, entry.getKey(), fieldMap);
                continue;
            }
            for (Object model : entry.getValue()) {
                i18nEntity.getSimpleFields().forEach(field -> {
                    I18nField i18nField = I18nReflectUtils.getI18nFieldAnnotation(field);
                    String nameMappingInPlatform = i18nField.value();
                    if (StringUtils.isEmpty(nameMappingInPlatform)) {
                        log.warn("I18nField 未定义value值，无法国际化,value : {}", nameMappingInPlatform);
                        return;
                    }
                    String substitution = fieldMap.get(nameMappingInPlatform);
                    log.debug("=====processSimpleField===>参数名字：{},========>值：{}", field.getName(), substitution);
                    try {
                        if (StringUtils.isNotBlank(substitution)) {
                            FieldUtils.writeField(field, model, substitution, true);
                        } else {
                            log.debug("字段：{},原始值：{},替换值：{}", field.getName(), nameMappingInPlatform, substitution);
                        }
                    } catch (Exception e) {
                        log.error("FlareOutTranslateExecute assemble field error", e);
                    }
                });
            }
        }
    }

    private void processCombinedField(List<Object> models, List<Field> combinedFields) {
        combinedFields.forEach(combinedField -> {
            I18nField i18nField = I18nReflectUtils.getI18nFieldAnnotation(combinedField);
            String systemCode = i18nField.systemCode();
            String businessCode = i18nField.businessCode();
            String businessKeyName = i18nField.businessKey();
            String fieldMappingInPlatform = i18nField.value();
            List<String> businessKeyListOfTheCombinedField = extractBusinessKeyList((List) models, businessKeyName);

            Map<String, Map<String, String>> idFieldsMapOfCombinedField = i18nInfoUtils.queryLocaleInfo(systemCode,
                    businessCode, GlobalUtils.getLanguage(), businessKeyListOfTheCombinedField);
            models.stream().forEach(model -> {
                Object businessKeyValue;
                try {
                    businessKeyValue = FieldUtils.readField(model, businessKeyName, true);
                    if (businessKeyValue != null) {
                        String businessKey = String.valueOf(businessKeyValue);
                        Map<String, String> fieldsMap = idFieldsMapOfCombinedField.get(businessKey);
                        if (fieldsMap != null) {
                            String substitution = fieldsMap.get(fieldMappingInPlatform);
                            if (StringUtils.isNotEmpty(substitution)) {
                                log.debug("====processCombinedField====>参数名字：{},========>值：{}",
                                        combinedField.getName(), substitution);
                                FieldUtils.writeField(combinedField, model, substitution, true);
                            }
                        }
                    }
                } catch (Exception e) {
                    log.error("error:", e);
                }
            });
        });
    }

    private void processCustomField(List<Object> models, List<Field> customFields) {
        if (CollectionUtils.isEmpty(customFields)) {
            return;
        }
        customFields.forEach(customField -> {
            I18nField i18nField = I18nReflectUtils.getI18nFieldAnnotation(customField);
            String metaCalculator = i18nField.metaCalculator();
            Translator calculator = i18nInfoUtils.getTranslator(metaCalculator);
            if (calculator == null) {
                log.error("自定义处理器：{} ,不存在，请查看代码", metaCalculator);
                return;
            }
            calculator.translate(models);
        });
    }

    private void processFields(Map<String, I18nEntity> map) {
        for (I18nEntity i18nEntity : map.values()) {
            // 简单属性处理
            processSimpleField(i18nEntity);

            List<Object> models = i18nEntity.getObjectList();

            // 处理自定义属性
            processCustomField(models, i18nEntity.getCustomFields());

            // 处理枚举对象
            processEnumField(models, i18nEntity.getEnumFields());
        }
    }

    private void initModel(List<Object> models, Map<String, I18nEntity> map) {
        if (CollectionUtils.isEmpty(models)) {
            return;
        }
        Object object = models.get(0);
        if (object == null) {
            log.warn("list中出现空对象: {}, {}", models, map);
            return;
        }
        Class<?> clazz = object.getClass();
        I18nModel i18nModel = I18nReflectUtils.getI18nModelAnnotation(clazz);
        if (i18nModel == null) {
            return;
        }
        // 判断是否是当前系统的对象（上游系统的国际化由上游系统处理，只翻译当前系统的对象）
        // 只判断最外层的对象
        if (!isCurrentSystemObject(i18nModel.systemCode())) {
            return;
        }
        String systemCode = i18nModel.systemCode();
        String businessCode = i18nModel.businessCode();
        String businessKeyName = i18nModel.businessKey();

        //简单属性处理
        List<Field> simpleFields = I18nReflectUtils.getSimpleFieldsListWithAnnotation(clazz);

        List<Field> combinedFields = I18nReflectUtils.getCombinedFieldsListWithAnnotation(clazz);

        List<Field> customFields = I18nReflectUtils.getCustomFieldsListWithAnnotation(clazz);

        List<Field> otherFields = I18nReflectUtils.getOtherFieldsListWithAnnotation(clazz);

        List<Field> enumFields = I18nReflectUtils.getEnumFields(clazz);

        I18nEntity i18nEntity = null;
        if (StringUtils.isNotBlank(businessCode)) {
            String name = clazz.getName();
            i18nEntity = map.get(name);
            if (i18nEntity == null) {
                i18nEntity = new I18nEntity(systemCode, businessCode, businessKeyName, simpleFields, combinedFields,
                        customFields, enumFields);
                map.put(name, i18nEntity);
            }
        } else {
            log.debug("当前对象无简单国际化属性,class：{}", clazz);
        }

        for (Object model : models) {
            try {
                if (StringUtils.isNotBlank(businessCode)) {
                    String id = String.valueOf(FieldUtils.readField(model, businessKeyName, true));
                    i18nEntity.putObject(id, model);
                }

                // 将组合属性融入到简单属性中一起处理
                for (Field field : combinedFields) {
                    I18nField i18nField = field.getAnnotation(I18nField.class);
                    String systemCode1 = i18nField.systemCode();
                    String businessCode1 = i18nField.businessCode();
                    String businessKeyName1 = i18nField.businessKey();
                    String mapKey = "&" + field.getType().getName();
                    I18nEntity combinedI18nEntity = map.get(mapKey);
                    if (combinedI18nEntity == null) {
                        combinedI18nEntity = new I18nEntity(systemCode1, businessCode1, businessKeyName1,
                                Lists.newArrayList(field));
                        map.put(mapKey, combinedI18nEntity);
                    }
                    String value = String.valueOf(FieldUtils.readField(model, businessKeyName1, true));
                    combinedI18nEntity.putObject(value, model);

                }

                // otherFields为空时递归结束
                for (Field field : otherFields) {
                    Object obj = FieldUtils.readField(model, field.getName(), true);
                    if (obj == null || Objects.equals(obj, "")) {
                        continue;
                    }
                    if (obj instanceof List) {
                        initModel((List<Object>) obj, map);
                    } else if (model instanceof Map) {

                        Collection values = ((Map) obj).values();
                        ArrayList list = new ArrayList<>(values);
                        if (CollectionUtils.isNotEmpty(list)) {
                            Object value = list.get(0);
                            //如果MAP的值本身就是一个list
                            if (value instanceof List) {
                                for (Object val : list) {
                                    initModel((List) val, map);
                                }
                            } else {
                                //如果value是一个正常的model
                                initModel(list, map);
                            }
                        }
                    } else {
                        initModel(Lists.newArrayList(obj), map);
                    }
                }
            } catch (IllegalAccessException e) {
                log.error("FlareOutTranslateExecute init map error：", e);
            }
        }
    }

    @Override
    public String name() {
        return NAME;
    }

    /**
     * 对枚举字段进行国际化
     * <p>
     * 需要依赖静态国际化的功能
     *
     * @param models
     * @param enumFields
     * @see com.haidechizi.i18n.common.enums.service.TranslateService
     */
    private void processEnumField(List<Object> models, List<Field> enumFields) {
        if (CollectionUtils.isEmpty(enumFields)) {
            return;
        }
        enumFields.forEach(enumField -> {
            try {
                I18nEnumField i18nEnumField = I18nReflectUtils.getEnumFieldAnnotation(enumField);
                // 当前对象中的enum唯一键对应的field名称
                String businessKey = i18nEnumField.businessKey();
                // 枚举中唯一键对应的字段名称
                String enumKey = i18nEnumField.enumKey();
                // 枚举对象
                Class<? extends Enum> clazz = i18nEnumField.clazz();
                // 获取枚举类中的静态对象
                Enum[] enumConstants = clazz.getEnumConstants();
                Map<String, Enum> enumMap = new HashMap<>();
                Field declaredField = clazz.getDeclaredField(enumKey);
                declaredField.setAccessible(true);
                for (Enum e : enumConstants) {
                    Object o = declaredField.get(e);
                    enumMap.put(String.valueOf(o), e);
                }
                models.forEach(model -> {
                    try {
                        // 获取当前对象中的枚举value
                        Object businessKeyValue = FieldUtils.readField(model, businessKey, true);
                        String value;
                        if (businessKeyValue == null || StringUtils.isBlank(value = String.valueOf(businessKeyValue))) {
                            return;
                        }
                        // 获取枚举对象
                        Enum anEnum = enumMap.get(value);
                        if (anEnum == null) {
                            return;
                        }
                        // 对枚举对象进行国际化
                        String forEnum = translateService.translateForEnum(anEnum);
                        if (StringUtils.isBlank(forEnum)) {
                            return;
                        }
                        // 将国际化的结果写回到当前对象
                        FieldUtils.writeField(enumField, model, forEnum, true);
                    } catch (Exception e) {
                        log.error("获取对象中的值出现异常", e);
                    }
                });
            } catch (Exception e) {
                log.error("枚举国际化异常", e);
            }

        });

    }
}
